package cn.edu.sdjzu.knoverse.utils;

import cn.dev33.satoken.stp.StpUtil;
import cn.edu.sdjzu.knoverse.constant.LocalDateTimeConstant;
import cn.edu.sdjzu.knoverse.constant.SaSessionConstant;
import cn.edu.sdjzu.knoverse.constant.UserConstant;
import cn.edu.sdjzu.knoverse.mapper.PowerMapper;
import cn.edu.sdjzu.knoverse.mapper.RoleMapper;
import cn.edu.sdjzu.knoverse.mapper.UserMapper;
import cn.edu.sdjzu.knoverse.model.entity.system.Power;
import cn.edu.sdjzu.knoverse.model.entity.system.Role;
import cn.edu.sdjzu.knoverse.model.entity.system.User;
import cn.edu.sdjzu.knoverse.model.vo.system.user.LoginVo;
import cn.edu.sdjzu.knoverse.utils.context.BaseContext;
import cn.edu.sdjzu.knoverse.utils.exception.CustomException;
import cn.edu.sdjzu.knoverse.utils.ip.IpUtil;
import cn.edu.sdjzu.knoverse.utils.minio.MinioUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class UserUtil {
    @Autowired
    private PowerMapper powerMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MinioUtil minioUtil;

    /**
     * 构建登录用户返回对象
     *
     * @param user      用户
     * @param readMeDay 保存登录信息时间
     * @return 登录信息
     */
    @Transactional(rollbackFor = CustomException.class)
    public LoginVo buildLoginUserVo(User user, long readMeDay) {
        Long userId = user.getId();
        String username = user.getUsername();

        // 获取IP地址并更新用户登录信息
        String ipAddr = IpUtil.getCurrentUserIpAddress().getIpAddr();
        String ipRegion = IpUtil.getCurrentUserIpAddress().getIpRegion();

        // 设置用户IP地址，并更新用户信息
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setIpAddress(ipAddr);
        updateUser.setIpRegion(ipRegion);
        userMapper.updateById(updateUser);

        // 设置用户返回信息
        LoginVo loginVo = setLoginVo(user, readMeDay, ipAddr, ipRegion);
        return loginVo;
    }

    /**
     * * 构建用户返回对象LoginVo
     *
     * @param user      用户对象
     * @param readMeDay 记住我时间
     */
    public void buildUserVo(User user, long readMeDay) {
        // 设置用户返回信息
        LoginVo loginVo = setLoginVo(user, readMeDay, user.getIpAddress(), user.getIpRegion());
        StpUtil.getSessionByLoginId(loginVo.getId()).set(SaSessionConstant.USER, loginVo);
    }


    /**
     * * 设置更新用户设置内容
     */
    public LoginVo setLoginVo(User user, long readMeDay, String ipAddr, String ipRegion) {
        Long userId = user.getId();

        // 判断用户是否有头像，如果没有头像设置默认头像，并且用户头像不能和默认头像相同
        String avatar = checkGetUserAvatar(user.getAvatar());

        // 查找用户角色
        List<String> roles = new ArrayList<>(roleMapper.selectListByUserId(userId).stream().map(Role::getRoleCode).toList());
        List<String> permissions = new ArrayList<>();

        permissions = powerMapper.selectListByUserId(userId).stream().map(Power::getPowerCode).toList();

        // 计算过期时间，并格式化返回
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime plusDay = localDateTime.plusDays(readMeDay);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS_SLASH);
        String expires = plusDay.format(dateTimeFormatter);

        // 构建返回对象，设置用户需要内容
        LoginVo loginVo = new LoginVo();
        BeanUtils.copyProperties(user, loginVo);
        loginVo.setNickname(user.getNickname());
        loginVo.setAvatar(avatar);
        loginVo.setIpAddress(ipAddr);
        loginVo.setIpRegion(ipRegion);
        loginVo.setRoles(roles);
        loginVo.setPermissions(permissions);
        loginVo.setUpdateUser(userId);
        loginVo.setSummary(user.getSummary());
        loginVo.setExpires(expires);
        loginVo.setReadMeDay(readMeDay);

        return loginVo;
    }

    /**
     * 检查用户头像是否合规
     *
     * @param avatar 头像字符串
     * @return 整理好的头像内容
     */
    public String checkPostUserAvatar(String avatar) {
        // 如果用户没有头像或者用户头像和默认头像相同，返回默认头像
        String userAvatar = UserConstant.USER_AVATAR;
        if (!StringUtils.hasText(avatar) || avatar.equals(userAvatar)) return userAvatar;

        // 替换前端发送的host前缀，将其删除，只保留路径名称
        String regex = "^https?://.*?/(.*)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(avatar);

        // 如果没有匹配
        if (!matcher.matches()) return avatar;

        // 匹配后返回内容
        return "/" + matcher.group(1);
    }

    /**
     * 检查用户头像是否合规
     *
     * @param avatar 头像字符串
     * @return 整理好的头像内容
     */
    public String checkGetUserAvatar(String avatar) {
        // 如果用户没有头像或者用户头像和默认头像相同，返回默认头像
        String userAvatar = UserConstant.USER_AVATAR;
        if (!StringUtils.hasText(avatar) || avatar.equals(userAvatar)) return userAvatar;

        // 替换前端发送的host前缀，将其删除，只保留路径名称
        String regex = "^https?://.*?/(.*)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(avatar);

        // 如果没有匹配
        if (matcher.matches()) return avatar;

        // 匹配后返回内容
        return minioUtil.getObjectNameFullPath(avatar);
    }
}